﻿using System;
using Microsoft.Xna.Framework;

namespace SaveTheQueen.Component
{
    public enum Sizing
    {
        KeepSize, StretchIfNeeded, AlwaysStretch
    }

    public class Container : ImageSprite
    {
        private Vector2 defautSize;
        private Vector2 margin;
        private Sizing sizing;
        private float spacing;
        private int maxElements;
        private int elementsCount = -1; // it must start as this, 'cause when a element is inserted, it will sum 1.
        private float currentHeight;

        public Vector2 DefautSize
        {
            get { return defautSize; }
        }
        public Vector2 Margin
        {
            get { return margin; }
            set { margin = value; CalcFactors(); Arrange(); }
        }
        public Sizing Sizing
        {
            get { return sizing; }
            set { sizing = value; CalcFactors(); Arrange(); }
        }
        public float Spacing
        {
            get { return spacing; }
            set { spacing = value; CalcFactors(); Arrange(); }
        }
        public int Capacity
        {
            get { return maxElements; }
        }
        public int ElementsCount
        {
            get { return elementsCount; }
        }

        public Container(string resource, int x, int y, int w, int h, GameObject owner, Core core)
            : base(resource, x, y, w, h, owner, core)
        {
            margin = this.Position * 0.03f;
            spacing = this.Position.Y * 0.02f;
            maxElements = 5;
            this.sizing = Sizing.StretchIfNeeded;

            CalcFactors();
        }
        public Container(string resource, Vector2 Margin, float Spacing, int Capacity, Sizing FitMethod, int x, int y, int w, int h, GameObject owner, Core core)
            : base(resource, x, y, w, h, owner, core)
        {
            this.margin = Margin;
            this.spacing = Spacing;
            this.maxElements = Capacity;
            this.sizing = FitMethod;

            CalcFactors();
        }


        public void AddElement(string resource, int w)
        {
            ImageSprite element = new ImageSprite(resource, 0, 0, w, (int)defautSize.Y, this, this.Game);
            AddElement(element);
        }
        public void AddElement(string text, string font)
        {
            TextSprite element = new TextSprite(text, font, 0, 0, this, this.Game);
            AddElement(element);
        }
        public void AddElement(Sprite element)
        {
            if (element != null)
            {
                if (elementsCount + 1 <= maxElements)
                {
                    elementsCount++;
                    this.Components.Add(element);

                    switch (sizing)
                    {
                        case Sizing.KeepSize:
                            break; // no changes
                        case Sizing.AlwaysStretch:
                            element.Size = defautSize;
                            break;
                        case Sizing.StretchIfNeeded:
                            Vector2 size = new Vector2(Math.Min(element.Size.X, defautSize.X), Math.Min(element.Size.Y, defautSize.Y));
                            element.Size = size;
                            break;
                    }

                    Vector2 pos;
                    pos.X = this.Position.X + margin.X;
                    pos.Y = currentHeight; // initially at this.position.Y + margin.Y
                    currentHeight += spacing + element.Size.Y;
                    element.Position = pos;
                }
                else
                {
                    throw new Exception("The Container is full.");
                }
            }
            else
            {
                throw new Exception("The element is null");
            }
        }

        private void CalcFactors()
        {
            defautSize = new Vector2(
                this.Size.X - 2 * margin.X,
                ((this.Size.Y - 2 * margin.Y) - spacing * (maxElements - 1)) / maxElements);

            currentHeight = this.Position.Y + margin.Y;
        }
        private void Arrange()
        {
            elementsCount = -1;
            int originalCount = this.Components.Count;
            for (int i = 0; i < originalCount; i++)
            {   // if i remove then here, i will skip 1 sprite for each remove.
                Sprite sp = (Sprite)this.Components[i];
                AddElement(sp);
            }
            for (int i = 0; i < originalCount; i++)
            {   // so i add the newer ones and then remove all the old ones. (if i use RemoveAt(i), it would remove some of the newers.
                this.Components.RemoveAt(0);
            }
        }
    }
}
